package org.litu.app.util;

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.litu.app.constant.SysContant;
import org.litu.util.Util;
import org.litu.util.file.FileUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 业务中涉及到的文件操作的工具类。为了统一当前应用的所有操作情况，包括路径、存储方式等。
 *
 * @author yueye
 */
@Slf4j
public class AppFileUtil {

    private final static String TEMP_FILE_DIR = "temp/";
    private final static String THUMBNAIL_FILE_DIR = "thumbnail/";

    /**
     * 规划几种文件类型，并对文件进行识别
     */
    private static Map<String, String[]> type = new HashMap<>();

    static {
        type.put("picture", new String[]{"jpg", "png", "jpeg", "gif", "tif", "bmp"});
        type.put("document", new String[]{"doc", "docx", "txt", "wps", "pdf", "rtf", "ini", "xml", "chm", "ftl"});
        type.put("code", new String[]{"sql", "bat", "java", "c", "html", "htm", "css", "js"});
        type.put("rar", new String[]{"zip", "rar", "gz", "jar", "exe",});
        type.put("audio", new String[]{"mp3", "mp4", "wav",});
        type.put("video", new String[]{"avi", "wmv", "rmvb", "flv", "mov"});
    }

    /**
     * 获取指定类型文件的所有后缀
     *
     * @param fileType
     * @return
     */
    public static String[] getFileTypeSuffix(String fileType) {
        return type.get(fileType);
    }

    /************* 正常文件操作 ***************/

    /**
     * 获取存储用文件的相对路径,带后缀则为文件，不带后缀则为路径
     *
     * @param fileType 文件类型, 获取路径，则传入：”“
     * @return
     */
    public static String getSavePath(String fileType) {
        // 文件名称、路径的处理
        String dirName = DateFormatUtils.format(new Date(), SysContant.FILE_PATH_PATTERN);

        String saveFileName = newFileName(fileType);
        // 相对路径
        String relativePath = dirName + saveFileName;

        return relativePath;
    }

    /**
     * 获取临时存储用文件的相对路径 ,带后缀则为文件，不带后缀则为路径
     *
     * @param fileType 文件类型, 获取路径，则传入：”“
     * @return
     */
    public static String getTempPath(String fileType) {
        // 文件名称、路径的处理
        String saveFileName = newFileName(fileType);
        // 相对路径
        String tempPath = TEMP_FILE_DIR + saveFileName;

        return tempPath;
    }

    /**
     * 新的文件名称生成
     *
     * @return
     */
    public static String newFileName(String fileType) {
        fileType = StringUtils.isBlank(fileType) ? "" : ("." + fileType);

        return Util.guId32() + fileType;
    }

    /**
     * 获取文件的真实路径
     *
     * @param relativePath
     * @return
     */
    public static String getRealPath(String relativePath) {
        return SysContant.FILE_BASE_PATH + relativePath;
    }


    /**
     * 根据相对路径，删除文件
     *
     * @param relativePath 文件的相对路径
     */
    public static void deleteFile(String fileType, String relativePath) {
        // 如果图片路径所对应的图片存在，则直接删除
        File nowfile = new File(AppFileUtil.getRealPath(relativePath));
        if (nowfile.exists()) {
            nowfile.delete();
        }

        //缩略图操作
        deleteThumbnail(fileType, relativePath);
    }

    /************* 缩略图操作 ***************/
    // 说明：缩略图和原图共用一个文件信息，只是存储路径存在区别

    /**
     * 获取缩略图的真实路径
     *
     * @param relativePath
     * @return
     */
    public static String getThumbnailRealPath(String relativePath) {
        return SysContant.FILE_BASE_PATH + THUMBNAIL_FILE_DIR + relativePath;
    }

    /**
     * 生成缩略图
     *
     * @param realPath     图片的真实路径
     * @param fileType     图片的类型
     * @param relativePath 图片的相对路径
     */
    public static void generateThumbnail(String realPath, String fileType, String relativePath) {
        // 如果设置生成缩略图，且文件为图片格式
        if (SysContant.THUMBNAIL_IMAGE && isImage(fileType)) {
            File thumbnailFile = new File(getThumbnailRealPath(relativePath));
            if (!thumbnailFile.exists()) {
                FileUtil.makeDirectory(thumbnailFile);

                try {
                    Thumbnails.of(realPath)
                            .size(280, 280)
                            .outputQuality(0.8f)
                            .toFile(thumbnailFile);
                } catch (IOException e) {

                }
            }
        }
    }

    /**
     * 删除缩略图
     *
     * @param fileType     图片的类型
     * @param relativePath 图片的相对路径
     */
    public static void deleteThumbnail(String fileType, String relativePath) {
        // 如果设置生成缩略图，且文件为图片格式
        if (SysContant.THUMBNAIL_IMAGE && isImage(fileType)) {
            File thumbnailFile = new File(getThumbnailRealPath(relativePath));
            // 如果图片路径所对应的图片存在，则直接删除
            if (thumbnailFile.exists()) {
                thumbnailFile.delete();
            }
        }
    }

    /************* 通过用方法 ***************/

    /**
     * 根据后缀判断是否是图片
     *
     * @param suffix
     * @return
     */
    public static boolean isImage(String suffix) {
        suffix = suffix.toLowerCase();
        String[] picSuffixs = type.get("picture");

        if (ArrayUtils.contains(picSuffixs, suffix)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 进行文件导出时，进行文件名称的编码的方法，因为不同浏览器的编码不同，避免乱码问题。
     *
     * @param fileName
     * @param request
     * @param response
     * @return
     */
    public static String encodeFileName(String fileName, HttpServletRequest request, HttpServletResponse response) {
        // 获取浏览器使用的编码
        String agent = request.getHeader("USER-AGENT");
        try {
            fileName = URLEncoder.encode(fileName, "UTF8");
        } catch (UnsupportedEncodingException e) {
            log.error("", e);
            fileName = RandomStringUtils.random(6, true, true);
        }
        // 如果没有UA，则默认使用IE的方式进行编码，因为毕竟IE还是占多数的
        String filenameConcat = "filename=\"" + fileName + "\"";
        if (agent != null) {
            agent = agent.toLowerCase();
            // IE浏览器，只能采用URLEncoder编码
            if (agent.indexOf("msie") != -1) {
                filenameConcat = "filename=\"" + fileName + "\"";
            }
            // Opera浏览器只能采用filename*
            else if (agent.indexOf("opera") != -1) {
                filenameConcat = "filename*=UTF-8''" + fileName;
            }
            // Safari浏览器，只能采用ISO编码的中文输出
            else if (agent.indexOf("safari") != -1) {
                try {
                    filenameConcat = "filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO8859-1") + "\"";
                } catch (UnsupportedEncodingException e) {
                    log.error("", e);
                    filenameConcat = "filename=\"" + fileName + "\"";
                }
            }
            // Chrome浏览器，只能采用MimeUtility编码或ISO编码的中文输出
            else if (agent.indexOf("applewebkit") != -1) {
                try {
                    fileName = URLEncoder.encode(fileName, "UTF8");
                } catch (UnsupportedEncodingException e) {
                    log.error("", e);
                }
                filenameConcat = "filename=\"" + fileName + "\"";
            }
            // FireFox浏览器，可以使用MimeUtility或filename*或ISO编码的中文输出
            else if (agent.indexOf("mozilla") != -1) {
                filenameConcat = "filename*=UTF-8''" + fileName;
            }
        }
        return filenameConcat;
    }
}
